#include<iostream>

#include<dirent.h> //文件夹系统相关库

#include<sys/stat.h>

#include"LinkTree.h"



std::string Double2(double num)  //写一个 保留两位小数的字符串的 函数
{
    return std::to_string ((1.0*(int)(num*100)) / 100);
}


std::string TransForm(size_t size)
{
    if(size < 1024)
        return std::to_string(size) + "B" ; //整型转换成字符串
    else if(size < 1024 * 1024)
        return Double2( (1.0 * size) / 1024 ) + "KB";
    else if(size < 1024*1024*1024)
        return Double2( (1.0 * size) / (1024*1024) )+ "MB";
    else 
        return Double2( (1.0 * size) / (1024*1024*1024) ) + "GB";
}

  //扫描文件夹
void ExploreDirectory(const std::string &path, TreeNode* node)
{
    //打开一个文件夹
    DIR *dir = opendir(path.c_str());  //.c_str 是把C++字符串 转化成 C语言 常量字符串
    
    if(dir == nullptr)
    {
        std::cout<<"文件夹路径有误! :"<<path<<std::endl;
        return;
    }

    //读取文件夹目录下的文件列表

    dirent *e = nullptr;
    
    while((e = readdir(dir)) != nullptr)
    {
        if(std::string(e->d_name) == "." || std::string(e->d_name) == "..")
            continue;

        TreeNode *child = new TreeNode(e->d_name);
        
        child->Connect(node); 

        if(e->d_type == DT_DIR)
        {
            ExploreDirectory(path + "/" + std::string(e->d_name), child);
        }
        else
        {
            struct stat s;                                          //转换 c 的字符串 到 c++ 
            stat( (path + "/" + std::string(e->d_name)).c_str(),&s);  //依赖于 .c_str
            child->SetData(std::string(e->d_name) + "       size:" + TransForm(s.st_size));
        }
    }


    //关闭目录流
    closedir(dir);
}

//把找到所有 名字叫name文件 的路径打印出来的功能抽出作单独功能
void Find(LinkTree &tree,const std::string &name) 
{
    DARRY::DynamicArray a = tree.FindByElementType(name);
    for(int i=0;i<a.Size();i++)
    {
        std::cout<<tree.GetNodePath((TreeNode*)a[i])<<std::endl;
    }
}

// argc代表命令行参数数量
// argv代表命令行参数值数组
int main(int argc,char * argv[])
{

    // std::cout<<argc<<std::endl;
    // for(int i=0;i<argc;i++)
    // {
    //     std::cout<<argv[i]<<std::endl; //循环打印 每个 命令行参数字符串
    // }


    std::string path;
    if(argc < 2)
    {
        path = "./";
    }
    else
    {
        path = argv[1];
    }

    LinkTree tree(path);

    ExploreDirectory(path,tree.GetRoot());
    
    // tree.show();

    // if(argc >= 3)
    // {
    //     Find(tree,argv[2]);
    // }
    // else
    // {
    //     std::cout<<"未输入查找的文件名!\n";
    // }

    struct stat s;//创建一个 stat类型的 新对象 s
    
    stat("./",&s);

    std::cout<<"文件大小:"<<s.st_size<<std::endl;//单位是 字节 

    tree.show();

    return 0;
}